using System;
using Habanero.Base;
using Habanero.BO;
using Habanero.BO.ClassDefinition;
using Habanero.UI.Base;
using Habanero.UI.Win;
using UseCaseManager.BO;

namespace UseCaseManager.UI
{
    /// <summary>
    /// A parent-child grid control used for adding and editing UseCases and their UseCaseSteps.
    /// </summary>
    public class UseCasesAndUseCaseStepsControl : UserControlWin, IFormControl
    {
        private readonly IControlFactory _controlFactory;
        private IReadOnlyGridControl _useCasesGridControl;

        public UseCasesAndUseCaseStepsControl(IControlFactory controlFactory)
        {
            _controlFactory = controlFactory;

            IReadOnlyGridControl useCasesGridControl = SetupParentControl();
            IGridControl useCaseStepsGridControl = SetupChildControl();

            // Add the grids to the control. The UseCases grid fills the top part of the control.  
            // Change the size here depending on how many items you want to see in this grid.  
            // The UseCaseSteps grid fills the rest of the control.
            BorderLayoutManager layoutManager = _controlFactory.CreateBorderLayoutManager(this);
            useCasesGridControl.Height = 200;
            layoutManager.AddControl(useCasesGridControl, BorderLayoutManager.Position.North, true);
            layoutManager.AddControl(useCaseStepsGridControl, BorderLayoutManager.Position.Centre);
            //useCasesGridControl.Buttons.AddButton("ChangeCollapse","Change To Collapsible", delegate
            //      {
            //          UseCasesGridControl.BusinessObjectEditor = new BOEditorWithCollapsiblePanel(_controlFactory);
            //      });
            //useCasesGridControl.Buttons.AddButton("ChangeGroup","Change To Group", delegate
            //      {
            //          UseCasesGridControl.BusinessObjectEditor = new BOEditorWithGroupPanel(_controlFactory);
            //      });
            //useCasesGridControl.Buttons.AddButton("ChangeTab","Change To Tab", delegate
            //      {
            //          UseCasesGridControl.BusinessObjectEditor = new DefaultBOEditor(_controlFactory);
            //      });
            // Connect the UseCases and UseCaseSteps grids so that when an item is selected
            // in the UseCases grid, the correct UseCaseSteps are shown in the child grid.
            useCasesGridControl.Grid.BusinessObjectSelected += 
                delegate
                    {
                        try
                        {
                            UseCase selectedUseCase = useCasesGridControl.Grid.SelectedBusinessObject as UseCase;
                            if (selectedUseCase == null) return;
                            useCaseStepsGridControl.BusinessObjectCollection = selectedUseCase.UseCaseSteps;
                        }
                        catch (Exception ex)
                        {
                            GlobalRegistry.UIExceptionNotifier.Notify(ex, "", "Error ");
                        }
                    };
        }

        public IReadOnlyGridControl UseCasesGridControl
        {
            get { return _useCasesGridControl; }
        }

        private IReadOnlyGridControl SetupParentControl()
        {
            // Create the UseCases read-only grid
            _useCasesGridControl = _controlFactory.CreateReadOnlyGridControl();

            // Used to specify a custom UI def
            UseCasesGridControl.Initialise(ClassDef.Get<UseCase>(), "default");

            // Load the collection of UseCases.  You can set the criteria and order by values here.
            BusinessObjectCollection<UseCase> useCasesCollection = Broker.GetBusinessObjectCollection<UseCase>("", "");
            UseCasesGridControl.BusinessObjectCollection=useCasesCollection;

            // Set this to true to enable the filters, then add your filters below (see commented out line)
            UseCasesGridControl.FilterControl.Visible = false;
            //useCasesGridControl.FilterControl.AddStringFilterTextBox("", "");

            // Uncomment this line to enable the default delete button
            //useCasesGridControl.Buttons.ShowDefaultDeleteButton = true;

            UseCasesGridControl.Buttons.Controls.Clear();

            return UseCasesGridControl;
        }

        private IGridControl SetupChildControl()
        {
            // Create the UseCaseSteps read-only grid to show the child items
            IGridControl useCaseStepsGridControl = _controlFactory.CreateEditableGridControl();

            // Used to specify a custom UI def
            useCaseStepsGridControl.Initialise(ClassDef.Get<UseCaseStep>(), "default");

            // Creates an empty collection of UseCaseSteps to put in the child grid
            BusinessObjectCollection<UseCaseStep> t2Collection = new BusinessObjectCollection<UseCaseStep>();
            useCaseStepsGridControl.BusinessObjectCollection=t2Collection;

            // Set this to true to enable the filters, then add your filters below (see commented out line)
            useCaseStepsGridControl.FilterControl.Visible = false;
            //useCaseStepsGridControl.FilterControl.AddStringFilterTextBox("", "");

            // Uncomment this line to enable the default delete button
            //useCaseStepsGridControl.Buttons.ShowDefaultDeleteButton = true;

            return useCaseStepsGridControl;
        }

        /// <summary>
        /// Called whenever the control is placed on a form by the menu system.  Put any initialisation
        /// code in here that must be run whenever the form is displayed.
        /// </summary>
        public void SetForm(IFormHabanero form) { }
    }

    internal class BOEditorWithCollapsiblePanel : DefaultBOEditor
    {

        public BOEditorWithCollapsiblePanel(IControlFactory controlFactory) : base(controlFactory)
        {
        }

        /// <summary>
        /// Edits the given business object by providing a form in which the
        /// user can edit the data
        /// </summary>
        /// <param name="obj">The business object to edit</param>
        /// <param name="uiDefName">The name of the set of ui definitions
        /// used to design the edit form. Setting this to an empty string
        /// will use a ui definition with no name attribute specified.</param>
        /// <returns>Returs true if the user chose to save the edits or
        /// false if the user cancelled the edits</returns>
        public override bool EditObject(IBusinessObject obj, string uiDefName)
        {
            BusinessObject bo = (BusinessObject)obj;
            IDefaultBOEditorForm form = CreateEditorForm(bo, uiDefName);
            return form.ShowDialog();
        }

        /// <summary>
        /// Edits the given object
        /// </summary>
        /// <param name="obj">The object to edit</param>
        /// <param name="uiDefName">The name of the set of ui definitions
        /// used to design the edit form. Setting this to an empty string
        /// will use a ui definition with no name attribute specified.</param>
        /// <param name="postEditAction">Action to be performed when the editing is completed or cancelled. Typically used if you want to update
        /// a grid or a list in an asynchronous environment (E.g. to select the recently edited item in the grid)</param>
        /// <returns>Returs true if edited successfully of false if the edits
        /// were cancelled</returns>
        public override bool EditObject(IBusinessObject obj, string uiDefName, PostObjectEditDelegate postEditAction)
        {
            BusinessObject bo = (BusinessObject)obj;
            IDefaultBOEditorForm form = CreateEditorForm(bo, uiDefName, postEditAction);
            return form.ShowDialog();
        }

        /// <summary>
        /// Creates a form in which a business object can be edited
        /// </summary>
        /// <param name="bo">The business object to edit</param>
        /// <param name="uiDefName">The name of the set of ui definitions
        /// used to design the edit form. Setting this to an empty string
        /// will use a ui definition with no name attribute specified.</param>
        /// <returns>Returns a DefaultBOEditorForm object</returns>
        protected override IDefaultBOEditorForm CreateEditorForm(BusinessObject bo, string uiDefName)
        {
            return _controlFactory.CreateBOEditorForm(bo, uiDefName, _controlFactory.CreateCollapsiblePanelGroupControl);
        }
        /// <summary>
        /// Creates a form in which a business object can be edited
        /// </summary>
        /// <param name="bo">The business object to edit</param>
        /// <param name="uiDefName">The name of the set of ui definitions
        /// used to design the edit form. Setting this to an empty string
        /// will use a ui definition with no name attribute specified.</param>
        /// <param name="action"></param>
        /// <returns>Returns a DefaultBOEditorForm object</returns>
        protected override IDefaultBOEditorForm CreateEditorForm(BusinessObject bo, string uiDefName, PostObjectEditDelegate action)
        {
            return _controlFactory.CreateBOEditorForm(bo, uiDefName, _controlFactory.CreateCollapsiblePanelGroupControl);
        }
    }
    internal class BOEditorWithGroupPanel : DefaultBOEditor
    {

        public BOEditorWithGroupPanel(IControlFactory controlFactory)
            : base(controlFactory)
        {
        }

        /// <summary>
        /// Edits the given business object by providing a form in which the
        /// user can edit the data
        /// </summary>
        /// <param name="obj">The business object to edit</param>
        /// <param name="uiDefName">The name of the set of ui definitions
        /// used to design the edit form. Setting this to an empty string
        /// will use a ui definition with no name attribute specified.</param>
        /// <returns>Returs true if the user chose to save the edits or
        /// false if the user cancelled the edits</returns>
        public override bool EditObject(IBusinessObject obj, string uiDefName)
        {
            BusinessObject bo = (BusinessObject)obj;
            IDefaultBOEditorForm form = CreateEditorForm(bo, uiDefName);
            return form.ShowDialog();
        }

        /// <summary>
        /// Edits the given object
        /// </summary>
        /// <param name="obj">The object to edit</param>
        /// <param name="uiDefName">The name of the set of ui definitions
        /// used to design the edit form. Setting this to an empty string
        /// will use a ui definition with no name attribute specified.</param>
        /// <param name="postEditAction">Action to be performed when the editing is completed or cancelled. Typically used if you want to update
        /// a grid or a list in an asynchronous environment (E.g. to select the recently edited item in the grid)</param>
        /// <returns>Returs true if edited successfully of false if the edits
        /// were cancelled</returns>
        public override bool EditObject(IBusinessObject obj, string uiDefName, PostObjectEditDelegate postEditAction)
        {
            BusinessObject bo = (BusinessObject)obj;
            IDefaultBOEditorForm form = CreateEditorForm(bo, uiDefName, postEditAction);
            return form.ShowDialog();
        }

        /// <summary>
        /// Creates a form in which a business object can be edited
        /// </summary>
        /// <param name="bo">The business object to edit</param>
        /// <param name="uiDefName">The name of the set of ui definitions
        /// used to design the edit form. Setting this to an empty string
        /// will use a ui definition with no name attribute specified.</param>
        /// <returns>Returns a DefaultBOEditorForm object</returns>
        protected override IDefaultBOEditorForm CreateEditorForm(BusinessObject bo, string uiDefName)
        {
            return _controlFactory.CreateBOEditorForm(bo, uiDefName, _controlFactory.CreateGroupBoxGroupControl);
        }
        /// <summary>
        /// Creates a form in which a business object can be edited
        /// </summary>
        /// <param name="bo">The business object to edit</param>
        /// <param name="uiDefName">The name of the set of ui definitions
        /// used to design the edit form. Setting this to an empty string
        /// will use a ui definition with no name attribute specified.</param>
        /// <param name="action"></param>
        /// <returns>Returns a DefaultBOEditorForm object</returns>
        protected override IDefaultBOEditorForm CreateEditorForm(BusinessObject bo, string uiDefName, PostObjectEditDelegate action)
        {
            return _controlFactory.CreateBOEditorForm(bo, uiDefName, _controlFactory.CreateGroupBoxGroupControl);
        }
    }
}
